package cn.monkey.chat.server.connect.chat.netty;

import cn.monkey.chat.server.connect.chat.ChatExchange;
import cn.monkey.chat.server.proto.Package;
import cn.monkey.io.transport.core.Exchange;
import cn.monkey.io.transport.core.server.FilterChain;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class SimpleNettyChatExchangeFactory implements NettyChatExchangeFactory {

    private final Logger log = LoggerFactory.getLogger(SimpleNettyChatExchangeFactory.class);

    private final FilterChain<ChatExchange, cn.monkey.chat.server.proto.Package> filterChain;

    public SimpleNettyChatExchangeFactory(FilterChain<ChatExchange, cn.monkey.chat.server.proto.Package> filterChain) {
        this.filterChain = filterChain;
    }

    private NettyChatExchange newExchange(String s, Channel channel) {
        return new SimpleNettyChatExchange(s, channel).bind();
    }

    @Override
    public NettyChatExchange apply(String s, Exchange exchange, Channel channel) {
        if (exchange == null) {
            NettyChatExchange newExchange = this.newExchange(s, channel);
            newExchange.inbound()
                    .receive(cn.monkey.chat.server.proto.Package.class)
                    .subscribe(pkg -> this.filterChain.doFilter(newExchange, pkg));
            return newExchange;
        }
        if (exchange instanceof SimpleDelegatesChatNettyExchange simpleDelegatesChatNettyExchange) {
            Collection<Exchange> delegates = simpleDelegatesChatNettyExchange.delegates();
            List<NettyChatExchange> list = new ArrayList<>();
            for (Exchange delegate : delegates) {
                if (delegate instanceof NettyChatExchange nettyChatExchange) {
                    list.add(nettyChatExchange);
                    continue;
                }
                log.error("invalid exchange type: {}", delegate.getClass());
                throw new IllegalArgumentException("invalid exchange type: " + delegate.getClass());
            }
            NettyChatExchange newExchange = this.newExchange(s, channel);
            list.add(newExchange);
            SimpleDelegatesChatNettyExchange nettyExchange = new SimpleDelegatesChatNettyExchange(s, list);
            newExchange.inbound()
                    .receive(cn.monkey.chat.server.proto.Package.class)
                    .subscribe(pkg -> this.filterChain.doFilter(nettyExchange, pkg));
            return nettyExchange;
        }
        if (exchange instanceof NettyChatExchange nettyChatExchange) {
            NettyChatExchange newExchange = this.newExchange(s, channel);
            SimpleDelegatesChatNettyExchange nettyExchange = new SimpleDelegatesChatNettyExchange(s, List.of(nettyChatExchange, newExchange));
            newExchange.inbound()
                    .receive(Package.class)
                    .subscribe(pkg -> this.filterChain.doFilter(nettyExchange, pkg));
            return nettyExchange;
        }
        throw new IllegalArgumentException("invalid exchange type: " + exchange.getClass());
    }
}
